package com.zzw.springboot.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzw.springboot.common.Constants;
import com.zzw.springboot.common.Result;
import com.zzw.springboot.entity.Files;
import com.zzw.springboot.service.IFilesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @Author zzw2000
 * @Date 2022-05-19 00:04:17
 * @Description 文件File前端控制器
 */
@RestController
@RequestMapping("/file")
public class FileController {
    @Value("${files.upload.path}")
    private String fileUploadPath;
    @Autowired
    private IFilesService filesService;

    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;

    /**
     * 文件上传
     *
     * @param file
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String fileType = FileUtil.extName(originalFilename);
        long size = file.getSize();
        //定义一个文件唯一标识
        String uuid = IdUtil.fastSimpleUUID();
        String fileUUID = uuid + StrUtil.DOT + fileType;
        File uploadFile = new File(fileUploadPath + fileUUID);
        File parentFile = uploadFile.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        String url;
        // 获取文件的md5
        String md5 = SecureUtil.md5(file.getInputStream());
        // 从数据库查询是否存在相同的记录
        //Files dbFiles = filesService.getOne(Wrappers.<Files>lambdaQuery().eq(Files::getMd5, md5));
        List<Files> files = filesService.list(Wrappers.<Files>lambdaQuery().eq(Files::getMd5, md5));
        if (files.size() != 0) {
            url = files.get(0).getUrl();
        } else {
            // 上传文件到磁盘
            file.transferTo(uploadFile);
            // 数据库若不存在重复文件，则不删除刚才上传的文件
            url = "http://localhost:9090/file/" + fileUUID;
        }

        Files saveFile = new Files();
        saveFile.setName(originalFilename);
        saveFile.setType(fileType);
        saveFile.setUrl(url);
        saveFile.setMd5(md5);
        saveFile.setSize(size / 1024);
        filesService.save(saveFile);
        //删除缓存
        redisTemplate.delete(Constants.FILES_KEY);
        return url;
    }

    /**
     * 文件下载  http://localhost:9090/file/{fileUUID}
     *
     * @param fileUUID
     * @param response
     * @throws IOException
     */
    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        //根据文件标识码获取文件
        File file = new File(fileUploadPath + fileUUID);
        //设置输出流格式
        ServletOutputStream os = response.getOutputStream();
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, StandardCharsets.UTF_8));
        response.setContentType("application/octet-stream");

        //读取文件的字节流
        os.write(FileUtil.readBytes(file));
        os.flush();
        os.close();
    }

    /**
     * 根据id删除数据（将is_delete字段设置为true）
     *
     * @param id
     * @return
     */
    @DeleteMapping("/{id}")
    public Result delete(@PathVariable("id") int id) {
        Files file = filesService.getById(id);
        file.setIsDelete(true);
        return Result.success(filesService.updateById(file));
    }

    /**
     * 根据id批量删除
     *
     * @param ids
     * @return
     */
    @PostMapping("/del/batch")
    public Result delete(@RequestBody List<Integer> ids) {
        List<Files> files = filesService.list(Wrappers.<Files>lambdaQuery().in(Files::getId, ids));
        for (Files file : files) {
            file.setIsDelete(true);
        }
        return Result.success(filesService.updateBatchById(files));
    }

    /**
     * 更改禁用链接
     *
     * @param files
     * @return
     */
    @PostMapping("/changeEnable")
    public Result changeEnable(@RequestBody Files files) {
        filesService.updateById(files);
        //删除缓存
        redisTemplate.delete(Constants.FILES_KEY);
        return Result.success();
    }

    /**
     * 分页查询
     *
     * @param pageNum
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    public Result findByPage(@RequestParam(defaultValue = "1") int pageNum,
                             @RequestParam(defaultValue = "10") int pageSize,
                             @RequestParam(defaultValue = "") String name) {
        IPage<Files> filesPage = filesService.page(new Page<>(pageNum, pageSize), Wrappers.<Files>lambdaQuery()
                .eq(Files::getIsDelete, false) //查询未删除的记录
                .like(StringUtils.isNotEmpty(name), Files::getName, name)
                .orderByDesc(Files::getId));
        return Result.success(filesPage);
    }

    @GetMapping("/detail/{id}")
    public Result VideoDetail(@PathVariable Integer id){
        return Result.success(filesService.getById(id));
    }
}

